<template>
  <div class="blog_container">
    <div class="quill_editor_area">
      <div class="op_btns">
        <el-button type="primary" plain size="small" @click="showBlogsDrawer">博客列表</el-button>
        <el-button type="primary" plain size="small" @click="showEditDialog" v-if="edit.isUploadMode">上传博客</el-button>
        <el-button type="primary" plain size="small" @click="showEditDialog" v-if="!edit.isUploadMode">修改博客</el-button>
      </div>
      <!-- 收集博客标题 -->
      <el-dialog :visible="edit.visible" title="博客信息" :before-close="hideEditDialog">
        <el-form label-width="100px">
          <el-form-item label="博客标题" required>
            <el-input v-model="blog.title" placeholder="输入博客标题" clearable></el-input>
          </el-form-item>
        </el-form>
        <span slot="footer">
          <el-button @click="hideEditDialog">取消</el-button>
          <el-button type="primary" v-if="edit.isUploadMode" @click="uploadBlog"
            v-show="uploadBlogStatus">确定上传</el-button>
          <el-button type="primary" v-if="!edit.isUploadMode" @click="editBlog" v-show="updateBlogStatus">确定修改</el-button>
        </span>
      </el-dialog>

      <!-- 事件：onchange,onblur,onready,onfocus -->
      <quill-editor v-model="blog.content" ref="editor" :options="quill.options" @paste.native="pasteHandle($event)">
      </quill-editor>

      <el-drawer title="博客列表" direction="rtl" size="800px" :visible="blogsDrawer.visible" :before-close="hideBlogsDrawer">
        <div class="blogs_area">
          <div>
            <el-button plain @click="getBlogs" size="small" v-show="getBlogStatus">刷新表格</el-button>
            <el-button plain @click="deleteBlogs" size="small" v-show="deleteBlogsStatus">批量删除</el-button>
            <el-button type="primary" plain size="small" @click="toUploadBlog">编写博客</el-button>
          </div>
          <el-table :data="mainTable.data" @selection-change="selectionChange">
            <template slot="empty">
              <el-empty description="什么博客都没有"></el-empty>
            </template>
            <!-- 复选列 -->
            <el-table-column type="selection"></el-table-column>
            <!-- 序号列 -->
            <el-table-column type="index" label="序号"></el-table-column>
            <!-- 展开列 -->
            <el-table-column type="expand" label="详情">
              <template slot-scope="{row}">
                <el-descriptions :title="row.originalFileName" :column="1" border size="small">
                  <el-descriptions-item :label="col.label" v-for="col in mainTable.expandColumns" :key="col.id">
                    <span>{{ row[col.prop] }}</span>
                  </el-descriptions-item>
                </el-descriptions>
              </template>
            </el-table-column>
            <!-- 动态列 -->
            <el-table-column show-overflow-tooltip="" :label="col.label" :prop="col.prop"
              v-for="col in mainTable.collumns" :key="col.id"></el-table-column>
            <!-- 操作列 -->
            <el-table-column label="操作" width="100px">
              <template slot-scope="{row}">
                <el-button size="small" @click="viewBlog(row)" v-show="getBlogStatus">查看</el-button>
              </template>
            </el-table-column>
          </el-table>
          <!-- 分页 -->
          <div style="padding:10px; display: flex; justify-content:space-around; ">
            <el-pagination hide-on-single-page layout="total, sizes, prev, pager, next, jumper" next-text="下一页"
              prev-text="上一页" @size-change="handleSizeChange" @current-change="handleCurrentChange"
              :current-page="mainTable.page.currentPage" :page-size="mainTable.page.pageSize"
              :total="mainTable.page.total">
            </el-pagination>
          </div>
        </div>
      </el-drawer>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
// 注册和配置富文本：图片尺寸调整、拖拽传入、粘贴图片
import Quill from 'quill'
import { ImageResize } from 'quill-image-resize-module'
Quill.register('modules/ImageResize', ImageResize);
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/imageDrop', ImageDrop)
import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'
Quill.register('modules/ImageExtend', ImageExtend)

export default {
  data() {
    return {
      edit: {
        visible: false,
        isUploadMode: true,
      },
      mainTable: {
        data: [],
        selection: [],
        page: {
          total: 0,
          currentPage: 1,
          pageSize: 10,
        },
        collumns: [
          {
            prop: 'title',
            label: '标题',
            minWidth: '80px'
          },
        ],
        // 展开列
        expandColumns: [
          {
            prop: 'id',
            label: 'ID',
          },
          {
            prop: 'createAt',
            label: '上传时间',
          },
          {
            prop: 'creatorName',
            label: '上传者',
          },
          {
            prop: 'updateAt',
            label: '更新时间',
          },
          {
            prop: 'updaterName',
            label: '更新者',
          },
        ],
      },
      quill: {
        options: {
          placeholder: '在此输入内容、粘贴图片、拖拽上传图片...',
          modules: {
            imageDrop: false,
            ImageResize: {
              handleStyles: {
                backgroundColor: 'black',
                border: 'none',
                borderRadius: '6px',
                // other camelCase styles for resize handles
              },
              displaySize: true,
              displayStyles: {
                backgroundColor: 'black',
                border: 'none',
                color: 'white',
                // other camelCase styles for size display
              }
            },
            ImageExtend: {
              name: 'file',
              action: `${this.$axios.defaults.baseURL}admin/blog/file/image`,
              size: 10,
              response: (res) => {
                if (res.code === 0) {
                  return this.$message.error(res.msg)
                } else if (res.code === 1) {
                  // 收集已上传的资源
                  this.blog.allFileSrcList.push(res.data[0])
                  return res.data[0] //返回资源的url，必要
                }
              },
              sizeError: () => { this.$message.warning('单个文件最大不能超过10M') },
              start: () => {
              },
              end: () => {
              },
              error: () => {
                this.$message.error('图片上传失败')
              },
              success: () => {
                if (this.uploadBlogImageStatus) {
                  this.$message.success('图片上传成功')
                }
              },
              // change: (xhr, formData) => {
              //   xhr.setRequestHeader('header1', 'value1')
              //   formData.append('token', sessionStorage.token)
              // },
              headers: (xhr) => { xhr.setRequestHeader('token', sessionStorage.token) }
            },
            toolbar: {
              container: container,
              handlers: {
                'image': function () {
                  QuillWatch.emit(this.quill.id)
                }
              }
            }
          }
        }
      },
      blog: {
        id: 0,
        title: "",
        content: "",
        unUsedFileSrcList: [],
        usedFileSrcList: [],
        allFileSrcList: [],
      },
      blogsDrawer: {
        visible: false,
      },
    }
  },

  computed: {
    // 借助mapGetters生成计算属性：uiAuthValidateIsNotNeeded、quillEditorAuths
    ...mapGetters('uiAuthModule', ['uiAuthValidateIsNotNeeded', 'quillEditorAuths']),
    // 详细计算各个操作的权限
    getBlogsStatus() {
      const { getBlogs: { finalStatus } } = this.quillEditorAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    deleteBlogsStatus() {
      const { deleteBlogs: { finalStatus } } = this.quillEditorAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    updateBlogStatus() {
      const { updateBlog: { finalStatus } } = this.quillEditorAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    getBlogStatus() {
      const { getBlog: { finalStatus } } = this.quillEditorAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    uploadBlogStatus() {
      const { uploadBlog: { finalStatus } } = this.quillEditorAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    uploadBlogImageStatus() {
      const { uploadBlogImage: { finalStatus } } = this.quillEditorAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
  },

  methods: {
    // 切换编辑模式为上传模式
    toUploadBlog() {
      this.edit.isUploadMode = true
      this.resetBlogEditingData()
      this.hideBlogsDrawer()
    },
    // 显示编辑对话框
    showEditDialog() {
      this.filterFileSrcList()
      this.edit.visible = true
    },
    // 隐藏编辑对话框
    hideEditDialog() {
      this.edit.visible = false
    },
    // 查看博客
    async viewBlog(blog) {
      // 非上传模式：编辑模式
      this.edit.isUploadMode = false
      this.resetBlogEditingData()
      const { data: res } = await this.$axios.get(`/admin/blog/${blog.id}`)
      if (res.code === 0) {
        return this.$message.error(res.msg)
      }
      const { id, title, content } = res.data
      this.blog.content = content
      this.blog.id = id
      this.blog.title = title
      this.hideBlogsDrawer()
      // 初始化文件引用列表
      this.$nextTick(() => {
        this.initFileSrcList()
      })
    },

    // 初始化文件引用列表
    initFileSrcList() {
      const blog = this.blog
      const imgs = document.querySelectorAll('.ql-editor img')
      if (imgs.length > 0) {
        imgs.forEach(img => {
          if (img.src.indexOf('base64') > 0) {
            // 删除base64编码的图片(太占数据库存储空间)
            img.remove()
          } else {
            // 使用的资源
            blog.usedFileSrcList.push(img.src)
            // 所有资源
            blog.allFileSrcList.push(img.src)
          }
        })
      }
    },

    // 重置博客编辑数据
    resetBlogEditingData() {
      const blog = this.blog
      blog.id = null
      blog.title = ''
      blog.content = ''
      blog.allFileSrcList = new Array()
      blog.unUsedFileSrcList = new Array()
      blog.usedFileSrcList = new Array()
    },

    // 过略资源
    filterFileSrcList() {
      const blog = this.blog
      const imgs = document.querySelectorAll('.ql-editor img')
      if (imgs.length <= 0) {
        blog.unUsedFileSrcList = blog.allFileSrcList
        blog.usedFileSrcList = []
      } else {
        const usedImgSrcs = new Array()
        imgs.forEach(img => {
          if (img.src.indexOf('base64') > 0) {
            img.remove()
          } else {
            usedImgSrcs.push(img.src)
          }
        })
        blog.usedFileSrcList = usedImgSrcs
        blog.unUsedFileSrcList = blog.allFileSrcList.filter(src => !usedImgSrcs.includes(src))
      }
    },

    // 编辑博客
    async editBlog() {
      this.filterFileSrcList()
      const { data: res } = await this.$axios({
        url: `/admin/blog/update`,
        method: 'put',
        data: this.blog
      })
      if (res.code === 0) {
        return this.$message.error(res.msg)
      }
      this.resetBlogEditingData()
      this.$message.success(res.msg)
      // 上传博客模式
      this.edit.isUploadMode = true
      this.hideEditDialog()
      this.getBlogs()
      this.showBlogsDrawer()
    },

    // 批量删除博客
    async deleteBlogs() {
      const selectedBlogs = this.mainTable.selection
      if (selectedBlogs.length <= 0) {
        return this.$message.warning(`请选择要删除的博客`)
      }
      const blogIds = selectedBlogs.map(blog => blog.id)
      const { data: res } = await this.$axios({
        url: `/admin/blog/batchDelete`,
        method: 'delete',
        data: blogIds,
      })
      if (res.code === 0) {
        return this.$message.error(res.msg)
      }
      this.$message.success(`已删除 ${res.data} 篇博客`)
      this.getBlogs()
    },

    // 表格复选变化处理
    selectionChange(selection) {
      this.mainTable.selection = selection
    },
    // 分页获取博客
    async getBlogs() {
      const table = this.mainTable
      const { data: res } = await this.$axios({
        url: `/admin/blog/page/${table.page.currentPage}/${table.page.pageSize}`,
      })
      if (res.code === 0) {
        return this.$message.error(res.msg)
      }
      table.data = res.data.data
      table.page.total = res.data.total
    },
    // 分页组件处理
    handleSizeChange(pageSize) {
      this.mainTable.page.pageSize = pageSize
      this.getBlogs()
    },
    handleCurrentChange(currentPage) {
      this.mainTable.page.currentPage = currentPage
      this.getBlogs()
    },

    // 上传博客
    async uploadBlog() {
      // 过滤图片
      this.filterFileSrcList()
      const { data: res } = await this.$axios({
        url: '/admin/blog/upload',
        method: 'post',
        data: this.blog
      })
      if (res.code === 0) {
        return this.$message.error(res.msg)
      }
      this.$message.success(res.msg)
      this.resetBlogEditingData()
      this.hideEditDialog()
      this.getBlogs()
      this.showBlogsDrawer()
    },

    // 显示博客列表
    showBlogsDrawer() {
      this.blogsDrawer.visible = true
    },
    // 隐藏博客列表
    hideBlogsDrawer() {
      this.blogsDrawer.visible = false
    },

    // 富文本粘贴事件处理：如果是图片，则上传至服务器，并通过 img 标签回显
    pasteHandle(evt) {
      // 判断粘贴板的数据
      if (
        evt.clipboardData &&
        evt.clipboardData.files &&
        evt.clipboardData.files.length
      ) {
        //阻止事件默认行为
        evt.preventDefault()

        const quill = this.$refs.editor.quill
        const files = evt.clipboardData.files

        for (let i = 0; i < files.length; i++) {
          // 文件（图片）类型匹配逻辑
          if (!files[i].type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) {
            return;
          }
          // 创建表单，并添加文件（图片）
          const fd = new FormData()
          fd.append('file', files[i])
          // 通过ajax请求上传粘贴的文件（图片）
          this.$axios.post('/admin/blog/file/image', fd)
            .then(res => {
              if (res.data.code === 1) {
                // 在富文本中插入<img>标签，标签的src属性为资源访问地址
                let selectionIndex = quill.getSelection().index
                quill.insertEmbed(selectionIndex, 'image', res.data.data[0])
                this.blog.allFileSrcList.push(res.data.data[0])
                quill.setSelection(selectionIndex + 1)
                this.$message.success(res.data.msg)
              } else if (res.data.code === 0) {
                this.$message.error(res.data.msg)
              } else {
                this.$message.warning('粘贴图片失败')
              }
            })
        }
      }
    }
  },

  mounted() {
    // 如果具有获取博客列表的权限
    if (this.getBlogsStatus) {
      this.getBlogs()
    }
  },
}
</script>

<style lang="less" scoped>
.blog_container {
  display: flex;
  justify-content: center;

  .quill_editor_area {
    width: 800px;

    .op_btns {
      padding: 0 0 10px 0;
    }

    .blogs_area {
      padding: 0 10px 0 10px;
    }
  }
}
</style>